package com.xls.dormitoryservice.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xls.base.exception.BusinessException;
import com.xls.dormitoryservice.entity.Room;
import com.xls.base.model.Student;
import com.xls.dormitoryservice.entity.Housing;
import com.xls.dormitoryservice.mapper.HousingMapper;
import com.xls.dormitoryservice.mapper.RoomMapper;
import com.xls.base.mapper.StudentMapper;
import com.xls.dormitoryservice.service.HousingService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xls.dormitoryservice.vo.HousingQuery;
import com.xls.dormitoryservice.vo.HousingVo;
import com.xls.entity.SecurityUser;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xls
 * @since 2021-03-23
 */
@Service
public class HousingServiceImpl extends ServiceImpl<HousingMapper, Housing> implements HousingService {

    @Autowired
    private HousingMapper housingMapper;

    @Autowired
    private RoomMapper roomMapper;

    @Autowired
    private StudentMapper studentMapper;

    @Override
    public HousingVo getHousing(String id) {
        return housingMapper.getHousing(id);
    }

    @Override
    @Transactional
    public HousingVo saveHousing(HousingVo housingVo) {
        Housing housing = new Housing();
        BeanUtils.copyProperties(housingVo, housing);
        validateHousing(housingVo, housing);
        this.save(housing);
        return housingMapper.getHousing(housing.getId().toString());
    }

    @Override
    @Transactional
    public HousingVo updateHousing(HousingVo housingVo) {
        Housing housing = new Housing();
        BeanUtils.copyProperties(housingVo, housing);
        validateHousing(housingVo, housing);
        this.updateById(housing);
        return housingMapper.getHousing(housing.getId().toString());
    }

    @Override
    @Transactional
    public void studentHousing(HousingVo housingVo) {
        SecurityUser securityUser = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String username = securityUser.getUsername();
        Student student = studentMapper.selectOne(new QueryWrapper<Student>().eq("sno", username));
        if (student == null) {
            throw new BusinessException(8888, "非学生用户不允许操作");
        }
        //入住-1 离宿-0
        if ("1".equals(housingVo.getType())) {
            if (student.getRoomId() != null) {
                throw new BusinessException(8888, "您已有宿舍");
            }
            Room room = roomMapper.selectById(housingVo.getRoomId());
            //存入住离宿表
            Housing housing = new Housing();
            housing.setStudentId(student.getId());
            housing.setRoomId(Long.valueOf(housingVo.getRoomId()));
            housing.setType(1);
            housing.setHobby(housingVo.getHobby());
            housing.setHabit(housingVo.getHabit());
            housing.setPlan(housingVo.getPlan());
            housingMapper.insert(housing);
            //存宿舍表
            if (room.getCurrent().equals(room.getCapacity())) {
                throw new BusinessException(77777, "宿舍人员已满");
            } else {
                roomMapper.update(new Room(), new UpdateWrapper<Room>().eq("id", room.getId()).set("current", room.getCurrent() + 1));
            }
            //存学生表
            studentMapper.update(new Student(), new UpdateWrapper<Student>().eq("id", student.getId()).set("room_id", room.getId()));
        } else {
            if (student.getRoomId() == null) {
                throw new BusinessException(8888, "您还没有入住宿舍");
            }
            Room room = roomMapper.selectById(student.getRoomId());
            //存入住离宿表
            Housing housing = new Housing();
            housing.setStudentId(student.getId());
            housing.setRoomId(student.getRoomId());
            housing.setType(0);
            housingMapper.insert(housing);
            //存宿舍表
            roomMapper.update(new Room(), new UpdateWrapper<Room>().eq("id", room.getId()).set("current", room.getCurrent() - 1));
            //存学生表
            studentMapper.update(new Student(), new UpdateWrapper<Student>().eq("id", student.getId()).set("room_id", null));
        }
    }

    private void validateHousing(HousingVo housingVo, Housing housing) {
        Student student = studentMapper.selectOne(new QueryWrapper<Student>().eq("sno", housingVo.getSno()));
        if (student == null) {
            throw new BusinessException(77777, "没有学号为" + housingVo.getSno() + "的学生");
        } else {
            housing.setStudentId(student.getId());
        }

        housing.setType(Integer.valueOf(housingVo.getType()));

        Housing lastHousing = housingMapper.selectOne(new QueryWrapper<Housing>()
                .eq("student_id", housing.getStudentId())
                .orderByDesc("gmt_create")
                .last("LIMIT 1"));
        // 校验学生是否能入住/离宿
        if (lastHousing != null) {
            if (housing.getType() == 1 && lastHousing.getType() == 1) {
                throw new BusinessException(7777, "学生已入住");
            } else if (housing.getType() == 0 && lastHousing.getType() == 0) {
                throw new BusinessException(7777, "学生未入住");
            }
        } else {
            if (housing.getType() == 0) {
                throw new BusinessException(7777, "学生未入住");
            }
        }

        Room room = roomMapper.selectOne(new QueryWrapper<Room>()
                .eq("building", housingVo.getBuilding())
                .eq("floor", housingVo.getFloor())
                .eq("rno", housingVo.getRno()));
        if (room == null) {
            throw new BusinessException(77777, "没有此宿舍");
        } else {
            housing.setRoomId(room.getId());
            // 入住/离宿
            if (housing.getType() == 1) {
                if (room.getCurrent().equals(room.getCapacity())) {
                    throw new BusinessException(77777, "宿舍人员已满");
                } else {
                    room.setCurrent(room.getCurrent() + 1);
                    roomMapper.updateById(room);
                    studentMapper.update(new Student(), new UpdateWrapper<Student>().eq("sno", student.getSno()).set("room_id", room.getId()));
                }
            } else {
                room.setCurrent(room.getCurrent() - 1);
                roomMapper.updateById(room);
                studentMapper.update(new Student(), new UpdateWrapper<Student>().eq("sno", student.getSno()).set("room_id", null));
            }
        }
    }

    @Override
    public Page<HousingVo> getHousingVoPage(Integer page, Integer limit, HousingQuery housingQuery) {
        QueryWrapper<Housing> housingQueryWrapper = new QueryWrapper<>();
        String building = housingQuery.getBuilding();
        String floor = housingQuery.getFloor();
        String rno = housingQuery.getRno();
        String studentId = housingQuery.getStudentId();
        String sno = housingQuery.getSno();
        String name = housingQuery.getName();
        String type = housingQuery.getType();
        String begin = housingQuery.getBegin();
        String end = housingQuery.getEnd();
        housingQueryWrapper
                .eq(!StringUtils.isEmpty(building), "r.building", building)
                .eq(!StringUtils.isEmpty(floor), "r.floor", floor)
                .likeRight(!StringUtils.isEmpty(rno), "r.rno", rno)
                .eq(!StringUtils.isEmpty(studentId), "h.student_id", studentId)
                .likeRight(!StringUtils.isEmpty(sno), "s.sno", sno)
                .likeRight(!StringUtils.isEmpty(name), "s.name", name)
                .eq(!StringUtils.isEmpty(type), "h.type", type)
                .gt(!StringUtils.isEmpty(begin), "h.gmt_create", begin)
                .lt(!StringUtils.isEmpty(end), "h.gmt_create", end)
                .eq("h.is_deleted", 0);
        return housingMapper.getHousingVoPage(new Page<>(page, limit), housingQueryWrapper);
    }

}
